/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package ru.dusty.fs.export;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import ru.dusty.fs.filesystem.data.Block;
import ru.dusty.fs.filesystem.data.BlockType;
import ru.dusty.fs.filesystem.data.MetaData;
import ru.dusty.fs.filesystem.utils.PrimitiveSizes;
import ru.dusty.fs.filesystem.utils.Utils;

/**
 *
 * @author Dusty
 */
public class ExportFs {
    
    private static final String NAME = "export";
    
    private byte[] getData(String root, Block firstBlock) throws IOException {
        if (firstBlock == null) return null;
        
        MetaData data = new MetaData();
        firstBlock.readMetaData(data);
        
        byte[] res = new byte[data.getSize()];
        
        int temp = 0;
        int sizeInBlock = Utils.getBlockSize(root) - PrimitiveSizes.sizeof(temp);
        int offset = sizeInBlock - data.getMetaDataSize();
        
        firstBlock.seek(data.getMetaDataSize());
        if (offset > res.length) {
            firstBlock.readData(res, 0, res.length);
        } else {
            firstBlock.readData(res, 0, offset);
        }
        int nextBlock = firstBlock.getNextBlock();
        while (nextBlock != 0) {
            Block block = new Block(new File(root + File.separator + nextBlock));
            block.seek(0);
            if (sizeInBlock > res.length - offset) {
                block.readData(res, offset, res.length - offset);
            } else {
                block.readData(res, offset, sizeInBlock);
            }
            offset += sizeInBlock;
            
            nextBlock = block.getNextBlock();
        }
        
        return res;
    }
    
    private void exportFile(String root, File hostFile, Block firstBlock) throws IOException {
        byte[] data = getData(root, firstBlock);
        
        if (data == null) return;
        
        FileOutputStream fos = new FileOutputStream(hostFile);
        fos.write(data);
        fos.close();
    }
    
    public int export(String[] args) {
        if (args.length < 3) {
            System.out.println(NAME + ": missing operand after \"" + NAME + "\"");
            System.out.println(NAME + ": use \"" + NAME + " root fs_file host_file\"");
            return 1;
        }
        
        String root = args[0];
        Block block;
        MetaData data = new MetaData();
        List<String> path = Utils.parsePath(args[1]);
        try {
            if (!Utils.isFsFormatted(root)) {
                System.out.println(NAME + ": File system error.");
                System.out.println(NAME + ": Use the command \"format root\"");
                return 5;
            }
            
            block = Utils.getFirstBlock(root, path);           
            if (block == null) {
                System.out.println(NAME + ": " + args[1] + ": file does not exist.");
                return 9;
            }
            
            block.readMetaData(data);
            if (data.getType().equals(BlockType.FOLDER)) {
                System.out.println(NAME + ": " + args[1] + ": is not a file.");
                return 10;
            }
        } catch (FileNotFoundException ex) {
            System.out.println(NAME + ": Could not find the file block.");
            System.out.println(NAME + ": " + ex.getMessage());
            return 2;
        } catch (IOException ex) {
            System.out.println(NAME + ": Error occurred while reading the file block.");
            System.out.println(NAME + ": " + ex.getMessage());
            return 3;
        }
        
        File hostFile = new File(args[2]);
        File parentFile = hostFile.getParentFile();
        
        parentFile.mkdirs();
        
        if (!parentFile.exists() || !parentFile.isDirectory()) {
            System.out.println(NAME + ": " + parentFile.getPath() + ": unable to create the directory.");
            return 6;
        }
        
        try {
            hostFile.createNewFile();
        } catch (IOException ex) {
            System.out.println(NAME + ": " + hostFile.getPath() + ": failed to create the file.");
            return 6;
        }
        
        if (!hostFile.isFile() || !hostFile.canWrite()) {
            System.out.println(NAME + ": " + hostFile.getPath() + ": is not a file or unavailable.");
            return 6;
        }
        
        try {
            System.out.println(NAME + ": Exporting the file...");
            
            exportFile(root, hostFile, block);
        } catch (FileNotFoundException ex) {
            System.out.println(NAME + ": Could not find the file block.");
            System.out.println(NAME + ": " + ex.getMessage());
            return 2;
        } catch (IOException ex) {
            System.out.println(NAME + ": Error occurred while reading the file block.");
            System.out.println(NAME + ": " + ex.getMessage());
            return 3;
        }
        
        System.out.println(NAME + ": Exporting completed successfully.");
        
        return 0;
    }
    
}
